package pl.edu.agh.ki.neuralnetwork.neurons;

import java.util.LinkedList;
import java.util.List;

import javax.swing.InputVerifier;

import pl.edu.agh.ki.neuralnetwork.exceptions.WrongArgException;

public class KohonenNeuron extends AbstractNeuron {

	private List<Neuron> inputNeuronsList;
	private List<Double> weights;
	private List<KohonenNeuron> neighbours = new LinkedList<KohonenNeuron>();
	private Double dist;
	private int i;
	private int j;

	public KohonenNeuron(List<Neuron> inputNeuronsList, List<Double> weights) {
		super(inputNeuronsList, weights);
		this.inputNeuronsList = inputNeuronsList;
		this.weights = weights;
	}

	public void addNeighBour(KohonenNeuron a) {
		neighbours.add(a);
	}

	public boolean isNeighBour(KohonenNeuron b) {
		return neighbours.contains(b);
	}

	public void setDist(List<Double> inputVector) throws WrongArgException {
		dist = d(inputVector, getWeights());
	}

	public double getDist() {
		return dist;
	}

	/**
	 * function measures distance between weights and inputs vector, used for
	 * choosing winner
	 * 
	 * @param inputVector
	 * @param weights
	 * @return
	 * @throws WrongArgException
	 */
	private Double d(List<Double> inputVector, List<Double> weights)
			throws WrongArgException {
		if (inputVector.size() != weights.size())
			throw new WrongArgException("" + inputVector.size() + " "
					+ weights.size());
		double sum = 0.0d;
		for (int i = 0; i < inputVector.size(); i++) {
			double a = inputVector.get(i);
			double b = weights.get(i);
//			System.out.println("a: "+a+", b: "+b);
			sum += (a - b) * (a - b);
		}
//		System.out.println("D: "+sum);
		return Math.sqrt(sum);
	}

	@Override
	public List<Double> getWeights() {
		List<Double> weightsList = new LinkedList<Double>();
		for (Neuron n : inputNeuronsList)
			weightsList.add(inputs.get(n));
		return weightsList;
	}
	public void setXY(int i, int j) {
		this.i = i;
		this.j = j;
	}
	public int getI() {
		return i;
	}

	public int getJ() {
		return j;
	}
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("\n[" + i+","+j+"] nb: ");
		for(KohonenNeuron kn : neighbours){
			sb.append("["+kn.getI()+"] ["+kn.getJ()+"] ");
		}
		int k =0;
		int sqrt = (int)Math.sqrt(inputNeuronsList.size());
		for (Double d : getWeights()){ 
			if (k% sqrt== 0)
				sb.append("\n");
			sb.append(d+" ");
			k++;
		}
		return sb.toString();
	}

	@Override
	public void compute() {
//		this.output = Math.abs(dist) ;
		this.output = 0.0;
		for(int i=0; i<inputNeuronsList.size(); i++) {
			Neuron input = inputNeuronsList.get(i);
			this.output += input.getOutput()*weights.get(i);
		}
	}

	public boolean isBias() {
		// TODO Auto-generated method stub
		return false;
	}
}

	
